﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraFlow : MonoBehaviour {
    public Transform target;
    public SysType type = SysType.零阶系统;
    public float error;
    [Header("二阶系统属性")]
    public float zeta = 0.6f;
    public float wn = 12f;
    [Header("一阶系统属性")]
    public float a = 1f;
    [Header("混合系统属性")]
    public float distance = 0.1f;
    [Header("缓存数据")]
    public float[] cn = new float[3];
    public float[] rn = new float[2];
    [Header("控制对象数据")]
    public Player player;
    public float speed;


    private void FixedUpdate()
    {
        if (player) speed = player.speed;
        rn[0] = target.position.x;
        float b0;
        float b1;
        float a1;
        float a2;
        switch (type)
        {
            case SysType.零阶系统:
                cn[0] = target.position.x;
                break;
            case SysType.一阶系统:
                b0 = Time.fixedDeltaTime * a / (1 + a * Time.fixedDeltaTime);
                a1 = -1 / (1 + a * Time.fixedDeltaTime);

                cn[0] = b0 * rn[0] - a1 * cn[1];
                break;
            case SysType.二阶系统:
                float fm = 1 + wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * wn * zeta * Time.fixedDeltaTime;
                b0 = wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime / fm;
                a1 = -(2 + 2 * wn * zeta * Time.fixedDeltaTime) / fm;
                a2 = 1 / fm;

                cn[0] = b0 * rn[0] - a1 * cn[1] - a2 * cn[2];
                break;
            case SysType.二型系统:
                float fm2 = 1 + wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * wn * zeta * Time.fixedDeltaTime;
                b0 = (wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * zeta * wn * Time.fixedDeltaTime) / fm2;
                b1 = -2 * zeta * wn * Time.fixedDeltaTime / fm2;
                a1 = -(2 + 2 * wn * zeta * Time.fixedDeltaTime) / fm2;
                a2 = 1 / fm2;

                cn[0] = b0 * rn[0] + b1 * rn[1] - a1 * cn[1] - a2 * cn[2];
                break;
            case SysType.二型_一阶混合系统:
                if (Mathf.Abs(error)<=distance)
                {
                    float fm4 = 1 + wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * wn * zeta * Time.fixedDeltaTime;
                    b0 = wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime / fm4;
                    a1 = -(2 + 2 * wn * zeta * Time.fixedDeltaTime) / fm4;
                    a2 = 1 / fm4;

                    cn[0] = b0 * rn[0] - a1 * cn[1] - a2 * cn[2];
                }
                else
                {
                    float fm3 = 1 + wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * wn * zeta * Time.fixedDeltaTime;
                    b0 = (wn * wn * Time.fixedDeltaTime * Time.fixedDeltaTime + 2 * zeta * wn * Time.fixedDeltaTime) / fm3;
                    b1 = -2 * zeta * wn * Time.fixedDeltaTime / fm3;
                    a1 = -(2 + 2 * wn * zeta * Time.fixedDeltaTime) / fm3;
                    a2 = 1 / fm3;

                    cn[0] = b0 * rn[0] + b1 * rn[1] - a1 * cn[1] - a2 * cn[2];
                }
                break;
            default:
                break;
        }
        cn[2] = cn[1];
        cn[1] = cn[0];
        rn[1] = rn[0];

        transform.position = new Vector3(cn[0], transform.position.y, transform.position.z);
        error = target.position.x - transform.position.x;
    }







    public enum SysType
    {
        零阶系统,
        一阶系统,
        二阶系统,
        二型系统,
        二型_一阶混合系统
    }
}
